(define-module (rectangular)
  #:use-module (rnrs base)
  #:use-module ((guile) #:select (lambda* λ simple-format))
  #:use-module (tagged-data)
  #:use-module (math)
  #:export (make-from-real-imag
            make-from-mag-ang
            rectangular?
            data-tag
            real-part
            imag-part
            magnitude
            angle
            install-package))

;;; IMPROVEMENT: Instead of renaming all procedures to have a prefix
;;; or suffix or some other means of telling what implementation they
;;; are from, we put them in a separate module and distinguish them
;;; upon importing them. This way neither one of the
;;; implementors/coders need to care about name collisions.

;;; NOTE: A module system is not yet introduced yet in the book at the
;;; point of this exercise.

;; representation in rectangular form
;; z = x + iy, i^2 = -1 -> point in a plane, real: x, imaginary: y

(define data-tag 'rectangular)

  ;;; Constructors.

(define make-from-real-imag
  (λ (real imag)
    (attach-tag data-tag
                (cons real imag))))

(define make-from-mag-ang
  (λ (mag ang)
    (attach-tag data-tag
                (cons (* mag (cos ang))
                      (* mag (sin ang))))))

  ;;; Accessors.

(define real-part
  (λ (num)
    (simple-format #t "real-part in rectangular num: ~a" num)
    (car num)))

(define imag-part
  (λ (num)
    (cdr num)))

(define magnitude
  (λ (num)
    (sqrt (+ (square (real-part num))
             (square (imag-part num))))))

(define angle
  (λ (num)
    (atan (imag-part num)
          (real-part num))))

(define rectangular?
  (λ (datum)
    (eq? (type-tag datum) data-tag)))


(define install-package
  (λ (lookup-table put)
    (let iter
        ([funcs° (list make-from-real-imag
                       make-from-mag-ang
                       rectangular?
                       data-tag
                       real-part
                       imag-part
                       magnitude
                       angle)])
      (cond
       [(null? funcs°) lookup-table]
       [else
        (put lookup-table op type func)
        (iter (cdr funcs°))]))))
